package com.offcn.seckill.task;

import com.offcn.common.utils.IdWorker;
import com.offcn.seckill.entity.SeckillStatus;
import com.offcn.seckill.mapper.SeckillGoodsMapper;
import com.offcn.seckill.pojo.SeckillGoods;
import com.offcn.seckill.pojo.SeckillOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * 多线程创建订单
 *
 * @author 秋林
 * @date 2022/10/19 14:29:36
 */

@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;


    /**
     * 多线程下单操作
     */
    @Async
    public void createOrder() {
        //从队列中获取排队操作
        SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();
        try {
            //从队列中获取一个商品
            Object sgood = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();
            if (sgood == null) {
                //清理当前用户的排队信息
                clearQueue(seckillStatus);
                return;
            }

            //时间区段
            String time = seckillStatus.getTime();
            //用户登录名
            String username=seckillStatus.getUsername();
            //用户抢购的商品
            Long id = seckillStatus.getGoodsId();

            //获取商品数据
            SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);

            //如果没有库存，则直接抛出异常
            if (StringUtils.isEmpty(goods) || goods.getStockCount()<=0) {
                throw new RuntimeException("已售完");
            }

            //如果有库存，则创建秒杀订单
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id);
            seckillOrder.setCreateTime(new Date());
            seckillOrder.setMoney(goods.getCostPrice());
            seckillOrder.setUserId(username);
            seckillOrder.setStatus("0");

            //将秒杀订单存入redis中
            redisTemplate.boundHashOps("seckillOrder").put(username,seckillOrder);

            //商品库存-1
            Long seckillGoodsCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(id, 1);
            goods.setStockCount(seckillGoodsCount.intValue());

            //判断当前商品是否还有库存
            if (seckillGoodsCount<= 0) {
                //并且将商品数同步到库存中
                seckillGoodsMapper.updateById(goods);
                //如果没有库存，则清空redis缓存中该商品
                redisTemplate.boundHashOps("SeckillGoods_"+time).delete(id);
            }else {
                //如果有库存，则直数据重置到Reids中
                redisTemplate.boundHashOps("SeckillGoods_" + time).put(id,goods);
            }

            //抢单成功，更新抢单状态，排队 —> 等待支付
            seckillStatus.setStatus(2);
            seckillStatus.setOrderId(seckillOrder.getId());
            seckillStatus.setMoney(Float.parseFloat(seckillOrder.getMoney()));
            redisTemplate.boundHashOps("UserQueueStatus").put(username,seckillStatus);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清除用户排队信息
     *
     * @param seckillStatus 秒杀状态
     */
    private void clearQueue(SeckillStatus seckillStatus) {
        //清理排队标示
        redisTemplate.boundHashOps("UserQueueCount").delete(seckillStatus.getUsername());

        //清理抢单标示
        redisTemplate.boundHashOps("UserQueueStatus").delete(seckillStatus.getUsername());
    }
}
